/*
 *Copyright (c) [2019-2020]  C2comm, Inc.  All rights reserved.
 *
 *This program is free software; you can redistribute it and/or
 *modify it under the terms of the GNU General Public License
 *as published by the Free Software Foundation; either version 2
 *of the License, or (at your option) any later version.
 *
 *This program is distributed in the hope that it will be useful,
 *but WITHOUT ANY WARRANTY; without even the implied warranty of
 *MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *GNU General Public License for more details.
 *
 *You should have received a copy of the GNU General Public License
 *along with this program; If not, see <https://www.gnu.org/licenses/>
 */

/*
 *Vendor: C2comm
 *Version: 1.0
 *Filename: PCFPermnt.v
 *Target Device: Altera
 *Author : sunxiaotian@c2comm.cn
*/

`timescale 1ns/1ps

module PCFPermnt(
    input wire SYS2CORE_clk,
	input wire SYS2CORE_rst_n,
	
	input wire [37:0] CONF2CORE_sys_conf,
    input wire [27:0] CONF2CORE_dbg_conf,
	input wire [47:0] DC2CORE_device_clk,
	input wire [19:0] CORE2SYS_local_clk,
	
	//input from PR
	input wire         PR2PPM_pcf_rx_des_wr,
	input wire [201:0] PR2PPM_pcf_rx_des,
	output wire  PR2PPM_pcf_rx_des_ready,
	//output to SM-Top
	output reg PPM2SM_pcf_rx_cb_wr,
	output reg [85:0] PPM2SCM_pcf_rx_cb, 
	input wire PPM2SM_pcf_rx_cb_ready,
	
	//output to CM-Top
	output reg PPM2CM_pcf_rx_cb_wr,
	input wire PPM2CM_pcf_rx_cb_ready
    );


reg pcf_rx_des_rd;
reg [201:0] cur_pcf_rx_des;
wire [201:0] pcf_rx_des_data;
wire full;
wire empty;
wire [5:0] data_count;

wire [47:0]  permanence_delay;

localparam IDLE_S = 2'b01,
		CALC_S = 2'b10;
		
reg [1:0] state;	
	
assign PR2PPM_pcf_rx_des_ready = !full;

assign permanence_delay[47:0] = CONF2CORE_sys_conf[19:0] + cur_pcf_rx_des[47:0] - cur_pcf_rx_des[86:67]- DC2CORE_device_clk[47:0];

always @(posedge SYS2CORE_clk or negedge SYS2CORE_rst_n) begin
	if(!SYS2CORE_rst_n) begin
		pcf_rx_des_rd <= 1'b0;
		PPM2SCM_pcf_rx_cb <= 86'b0;
		cur_pcf_rx_des <= 202'b0;
		PPM2SM_pcf_rx_cb_wr <= 1'b0;
		PPM2CM_pcf_rx_cb_wr <= 1'b0;
		pcf_rx_des_rd <= 1'b0;
		state <= IDLE_S;
	end
	else begin
		case(state) 
			IDLE_S: begin
				if(!empty) begin
					pcf_rx_des_rd <= 1'b1;
					cur_pcf_rx_des <= pcf_rx_des_data;
					PPM2SM_pcf_rx_cb_wr <= 1'b0;
					PPM2CM_pcf_rx_cb_wr <= 1'b0;
					state <= CALC_S;
				end
				else begin
				    PPM2SM_pcf_rx_cb_wr <= 1'b0;
					PPM2CM_pcf_rx_cb_wr <= 1'b0;
					cur_pcf_rx_des <= 202'b0;
					state <= IDLE_S;
				end
			end
			CALC_S: begin
				if((PPM2SM_pcf_rx_cb_ready == 1'b1 && CONF2CORE_sys_conf[21:20] == 2'b10 ) || (PPM2CM_pcf_rx_cb_ready == 1'b1 && CONF2CORE_sys_conf[21:20] == 2'b11)) begin
					PPM2SCM_pcf_rx_cb[1:0] <= cur_pcf_rx_des[197:196];
					PPM2SCM_pcf_rx_cb[7:2] <= cur_pcf_rx_des[169:164];
					PPM2SCM_pcf_rx_cb[15:8] <= cur_pcf_rx_des[139:132];
					if(cur_pcf_rx_des[115:112] == 4'h4) begin PPM2SCM_pcf_rx_cb[17:16] <= 2'b00; end//CS
					else if(cur_pcf_rx_des[115:112] == 4'h8) begin PPM2SCM_pcf_rx_cb[17:16] <= 2'b01;end//CA
					else if(cur_pcf_rx_des[115:112] == 4'h2)  begin PPM2SCM_pcf_rx_cb[17:16] <= 2'b10;end//IN
					else begin PPM2SCM_pcf_rx_cb[17:16] <= 2'b11;end //unknown
					
					*/
					PPM2SCM_pcf_rx_cb[37:18] <= CORE2SYS_local_clk[19:0]+permanence_delay[19:0];
					PPM2SCM_pcf_rx_cb[85:38] <= CONF2CORE_sys_conf[19:0] + cur_pcf_rx_des[47:0] - cur_pcf_rx_des[86:67];
					
					if(CONF2CORE_sys_conf[21:20] == 2'b10) begin  //SM
						PPM2SM_pcf_rx_cb_wr <= CONF2CORE_dbg_conf[26];
						
					end
					else if(CONF2CORE_sys_conf[21:20] == 2'b11) begin  //CM
						PPM2CM_pcf_rx_cb_wr <= CONF2CORE_dbg_conf[26];
						
					end
					else begin //SC
						PPM2SM_pcf_rx_cb_wr <= 1'b0;
					    PPM2CM_pcf_rx_cb_wr <= 1'b0;
					end
					pcf_rx_des_rd <= 1'b0;
					state <= IDLE_S;
				end
				else begin
					pcf_rx_des_rd <= 1'b0;
					PPM2SM_pcf_rx_cb_wr <= 1'b0;
					PPM2CM_pcf_rx_cb_wr <= 1'b0;
					state <= CALC_S;
				end
			end
			default: begin
				pcf_rx_des_rd <= 1'b0;
				PPM2SCM_pcf_rx_cb <= 86'b0;
				cur_pcf_rx_des <= 202'b0;
				PPM2SM_pcf_rx_cb_wr <= 1'b0;
				PPM2CM_pcf_rx_cb_wr <= 1'b0;
				state <= IDLE_S;
			end
		endcase
	end
end

pcf_des_fifo pcf_des_fifo_inst(
.clock(SYS2CORE_clk),
.data(PR2PPM_pcf_rx_des),
.wrreq(PR2PPM_pcf_rx_des_wr & CONF2CORE_dbg_conf[26]),
.rdreq(pcf_rx_des_rd),
.q(pcf_rx_des_data),
.full(full),
.empty(empty),
.usedw(data_count)
);
	
endmodule
